package org.zerta.troops.common;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.LinkedList;

import org.zerta.troops.server.ServerConsole;

public class Game {

	private Map <String, Player> players;
	private World world;
	private String name;
	private List<Turn> turns;
	private Turn currentTurn;
	private Turn lastProcessedTurn;
	private boolean started;
	private ServerConsole console;
	private int turnCounter;
	private boolean isFull;


	public Game () {
		players = new HashMap<String, Player>();
		
		turnCounter = 0;
		turns = new LinkedList<Turn>();
		
		currentTurn = new Turn(this, turnCounter++);
		turns.add(currentTurn);
		started = false;
		isFull = false;
	}
	
	public World getMap() {
		return world;
	}

	public void setMap(World world) {
		this.world = world;
	}
	
	public Player findPlayer( String name ) {
		if (players.containsKey(name.toLowerCase())) {
			return players.get(name.toLowerCase());
		} else {
			return null;
		}
	}
	
	public boolean addPlayer( Player player ) {
		if (player == null) {
			console.log("Player is null");
			return false;
		} else if (started) {
			console.log("Cannot join game since the game is already started");
			return false;
		} else if (isFull) {
			console.log("Cannot join game since the game is full");
			return false;
		} else {
			if (world !=  null) {

				synchronized(this) {
					if (players.containsKey(player.getName())) {
						console.log("Not adding player " + player.getName() + " - Player is already added");
						return false;
					} else {
						
						Map <String, Area> areas = world.getAreas();
						List <Area> emptyAreas = new LinkedList<Area>();
						for (Area area: areas.values()) {
							if (area.getOwner() == null) {
								emptyAreas.add(area);
							}
						}
						if (emptyAreas.size() == 0) {
							console.log("Game is full!");
							return false;
						}
						
						console.log("Adding player " + player.getName());
						players.put(player.getName().toLowerCase(), player);

						int chosenAreaInt = (int) (Math.random() * emptyAreas.size());
						Area chosenArea = emptyAreas.get(chosenAreaInt);
						console.log("Giving area " + chosenArea.getName() + " to player " + player.getName());
						chosenArea.setOwner(player);
						player.addAreaWithPresence(chosenArea);
						return true;
					}
				}

			} else {
				return false;
			}
		}
	}

	public Map<String, Player> getPlayers() {
		return players;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	public String toString() {
		return getName();
	}
	
	public void addTurnData ( TurnData turnData ) {
		currentTurn.addTurnData(turnData);
	}
	
	public boolean allPlayersSubmittedCurrentTurn() {
		return currentTurn.allPlayersSubmitted();
	}
	
	public Turn getCurrentTurn() {
		return currentTurn;
	}
	
	public void advanceTurn() {
		Turn newTurn = new Turn(this, turnCounter++);
		turns.add(newTurn);
		currentTurn = newTurn;
	}
	
	public void setLastProcessedTurn(Turn lastProcessedTurn) {
		console.log("Finished processing turn");
		this.lastProcessedTurn = lastProcessedTurn;
	}
	
	public Turn getLastProcessedTurn() {
		return lastProcessedTurn; 
	}
	
	public void startGame() {
		started = true;
	}
	
	public boolean isStarted() {
		return started;
	}

	public void setConsole(ServerConsole console) {
		this.console = console;
	}
	
}
